import {
  IPublicTypeJSExpression,
  IPublicTypeNodeSchema,
  IPublicTypeProjectSchema,
  IPublicTypeRootSchema,
} from '@alilc/lowcode-types';

import { parseToCssCode, parseToStyleData, transformStyleData } from './cssCode';

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { toCSS, toJSON } from 'cssjson';
import { chineseToEnglish } from '../../utils/chineseToEnglish';

const ignoreStyleClassComponent = ['Modal'];

const shortComponentName: Record<string, string> = {
  ScrollView: 'sv',
  View: 'vw',
  ImageBackground: 'ibg',
  Text: 'tx',
};

function getShortComponentName(name: string) {
  return shortComponentName[name] || name;
}

/**
 * 将 Tailwind CSS 类名中的特殊字符转换为有效的 CSS 类名
 * @param className 原始类名
 * @returns 转义后的类名
 */
function sanitizeTailwindClassName(className: string): string {
  return className
    .replace(/:/g, '__') // 冒号转换为双下划线 (lg:col-span-2 -> lg__col-span-2)
    .replace(/\//g, '_') // 斜杠转换为单下划线 (w-1/2 -> w-1_2)
    .replace(/\./g, '__') // 点转换为双下划线 (text-sm.5 -> text-sm__5)
    .replace(/%/g, 'pct') // 百分号转换为 pct (w-50% -> w-50pct)
    .replace(/\[/g, '_') // 左方括号转换为下划线 (text-[14px] -> text-_14px_)
    .replace(/\]/g, '_') // 右方括号转换为下划线
    .replace(/#/g, 'hash'); // 井号转换为 hash (bg-[#ff0000] -> bg-_hashff0000_)
}

/**
 * 检测样式对象是否包含表达式，避免将表达式样式转换为 className
 * @param style 样式对象
 * @returns 是否包含表达式
 */
function isExpressionStyle(style: any): boolean {
  if (!style || typeof style !== 'object') return false;

  // 检查标准 JSExpression 格式
  if (style.type === 'JSExpression') return true;

  // 检查样式值是否包含表达式
  for (const value of Object.values(style)) {
    if (typeof value === 'object' && (value as any).type === 'JSExpression') {
      return true;
    }
    if (
      typeof value === 'string' &&
      (value.includes('this.') || value.includes('props.') || value.includes('state.'))
    ) {
      return true;
    }
  }

  return false;
}

export const transformSchemaStyleToCss = async (
  schema: IPublicTypeProjectSchema,
  solution: any,
) => {
  const { componentsTree } = schema;
  const _componentsTree = [];
  for (let index = 0; index < componentsTree.length; index++) {
    const documentNode = componentsTree[index];
    // console.log('[documentNode] ', typeof documentNode, documentNode);
    const {
      title: _title,
      fileName,
      css,
    } = typeof documentNode === 'string' ? JSON.parse(documentNode) : documentNode;
    // console.log('[TRANSFORM_STYLE] ', _title, fileName);
    const cssJson = toJSON(css);
    let dulicateStyleNum = 0;
    const transformNode = async (
      node: IPublicTypeRootSchema | IPublicTypeNodeSchema | any,
      i: number,
      parentNode?: IPublicTypeNodeSchema,
    ) => {
      const { id, title, props = {}, children } = node;
      if (props) {
        const { style } = props as any;
        // 删除xxx.xxx的字段
        const keys = Object.keys(props || {});
        for (let i = 0; i < keys.length; i++) {
          const key = keys[i];
          if (key.includes('.')) {
            delete props[key];
          }

          if (props[key]?.type === 'JSSlot' && Array.isArray(props[key]?.value)) {
            const items = props[key].value;
            for (let index = 0; index < items.length; index++) {
              const item = items[index];
              await transformNode(item, index, node);
            }
          }

          if (Array.isArray(props[key])) {
            const items = props[key];
            for (let index = 0; index < keys.length; index++) {
              const item = items[index];
              if (item?.componentName) {
                await transformNode(item, index, node);
              } else {
                if (typeof item === 'object') {
                  const childKeys = Object.keys(item || {});
                  for (let i = 0; i < childKeys.length; i++) {
                    const key = childKeys[i];
                    if (item[key]?.type === 'JSSlot' && Array.isArray(item[key].value)) {
                      const childs = item[key].value;
                      for (let index = 0; index < childs.length; index++) {
                        const item = childs[index];
                        await transformNode(item, index, node);
                      }
                    } else if (Array.isArray(item[key])) {
                      const childs = item[key];
                      for (let index = 0; index < childs.length; index++) {
                        const item = childs[index];
                        if (item?.componentName) await transformNode(item, index, node);
                      }
                    }
                  }
                }
              }
            }
          }
        }
        // 删除无用的字段
        if (props.inlineStyle === '' || props.inlineStyle?.length === 0) {
          delete props.inlineStyle;
        }
        if (node.componentName === 'Text' && props.children === '') {
          delete props.children;
        }
        // 移除占位区域
        if (props.__hidePh) delete props.__hidePh;
        if (node.componentName === 'HeaderBar' && typeof props.loginIcon !== 'undefined') {
          delete props.loginIcon;
        }

        // 处理style
        const styleKeys = style ? Object.keys(style) : [];
        if (
          !ignoreStyleClassComponent.includes(node.componentName) &&
          style &&
          styleKeys.length > 0 &&
          !isExpressionStyle(style) &&
          !(style as IPublicTypeJSExpression)?.type
        ) {
          // 处理RN不支持display: inline，将其转换为Text组件
          if (style.display === 'inline') {
            // 只有子元素是Text才把自身替换成Text
            if (node.children?.[0]?.componentName === 'Text') {
              node.componentName = 'Text';
              delete style.flexDirection;
              delete style.justifyContent;
              delete style.alignItems;
            }
            // 扔闪删掉inline
            delete style.display;
          }
          if (style.fontWeight) {
            style.fontWeight = String(style.fontWeight);
          }
          if (style.boxShadow) {
            // console.log('box-shadow: ', style.boxShadow);
          }
          // 删除空值字段
          styleKeys.forEach((k) => {
            if (style[k] === '') {
              delete style[k];
            }
            if (style[k] && typeof style[k] === 'string' && style[k].includes('calc')) {
              style[k] = style[k].replace(' ', '&nbsp;').replace(' ', '&nbsp;');
            }
          });
          // 生成styleClass
          let styleClassName = id || `${getShortComponentName(node.componentName)}_${String(i)}`;
          const extClassName: string[] = [];
          if (title) {
            const englishName = await chineseToEnglish(title);
            styleClassName = englishName.text;
          } else {
            // 根据在父级中的位置生成节点className
            if (parentNode) {
              styleClassName = getShortComponentName(node.componentName) + (i > 0 ? String(i) : '');
            }
            // BEM 命名
            if (
              parentNode?.props?.className &&
              typeof parentNode?.props?.className === 'string' &&
              parentNode?.id !== parentNode?.props?.className
            ) {
              // 获取父级的第一个类名并处理 Tailwind CSS 特殊字符
              const parentClassName = (parentNode?.props?.className as string)?.split(' ')[0];
              const sanitizedParentClassName = sanitizeTailwindClassName(parentClassName);
              styleClassName = `${sanitizedParentClassName}__${styleClassName}`;
            }
          }
          if ((style as any).flex === 1 || (style as any).flexGrow === 1) {
            delete (style as any).flex;
            extClassName.push('M-flex-item');
          }
          // 增加文件名前缀
          if (!styleClassName.includes(fileName)) {
            styleClassName = `${fileName}__${styleClassName}`;
          }
          // 处理重名
          if (cssJson.children[`.${styleClassName}`]) {
            dulicateStyleNum++;
            styleClassName = `${styleClassName}_${dulicateStyleNum}`;
          }

          if (styleClassName.includes('"')) {
            styleClassName = styleClassName.replace(/"/g, '');
          }

          // 存入css文件 - 确保 CSS 选择器中的特殊字符被正确转义
          const cssSelector = sanitizeTailwindClassName(styleClassName);
          cssJson.children[`.${cssSelector}`] = {
            children: {},
            attributes: transformStyleData(style, solution),
          };
          // 生成的className在最前，classNameSetter的在中，自动补充的在后
          // 注意：只转义我们生成的 styleClassName，保持原有的 Tailwind 类名不变
          const sanitizedStyleClassName = sanitizeTailwindClassName(styleClassName);
          const classNameStr = [
            sanitizedStyleClassName,
            typeof props.className === 'string' ? props.className : '',
            extClassName.length > 0 ? ` ${extClassName.join(' ')}` : '',
          ]
            .filter(Boolean)
            .join(' ');
          if (typeof props.className === 'object' && props.className.type === 'JSExpression') {
            props.className.value = `(${props.className.value}) + ' ${classNameStr}'`;
          } else {
            props.className = classNameStr;
          }
          delete props.style;
        }
        if (children && Array.isArray(children) && children.length > 0) {
          const _children = [];
          for (let _i = 0; _i < children.length; _i++) {
            const _node = children[_i];
            _children.push(await transformNode(_node as IPublicTypeNodeSchema, _i, node));
          }
          node.children = _children;
        } else {
          // 处理JSSolt
          const propsKeys = Object.keys(props || {});
          for (let ii = 0; ii < propsKeys.length; ii++) {
            const pk = propsKeys[ii];
            if (props[pk]?.type === 'JSSlot' && props[pk]?.value?.length > 0) {
              const { children: _children } = await transformNode({ children: props[pk].value }, 0);
              props[pk].value = _children;
            }
          }
        }
      }
      if (typeof node === 'object') node.props = props;
      return node;
    };
    const _node = (await transformNode(documentNode, index)) as IPublicTypeRootSchema;
    _node.css = toCSS(cssJson);
    _componentsTree.push(_node);
  }
  return schema;
};
